package com.woniu.mealsService.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.annotation.RequireRole;
import com.woniu.dto.StoreAppliesDto;
import com.woniu.dto.StoreApplyFileDto;
import com.woniu.dto.StoreApplyPageDto;
import com.woniu.dto.StoreDto;
import com.woniu.exception.XinanException;
import com.woniu.exception.meals.StoreException;
import com.woniu.form.ApplyForStoreForm;
import com.woniu.form.InsertStoreForm;
import com.woniu.form.ModifyStoreForm;
import com.woniu.form.StoreOpenTimeForm;
import com.woniu.mealsService.model.Product;
import com.woniu.mealsService.model.Store;
import com.woniu.mealsService.service.CommentService;
import com.woniu.mealsService.service.ProductService;
import com.woniu.mealsService.service.StoreService;
import com.woniu.param.ApplyForStoreParam;
import com.woniu.param.InsertStoreParam;
import com.woniu.param.ModifyStoreParam;
import com.woniu.param.StoreOpenTimeParam;
import com.woniu.server.RedisKey;
import com.woniu.server.RedisUtil;
import com.woniu.user.client.UserFeignClient;
import com.woniu.user.dto.UserInfoFeignDto;
import com.woniu.utils.EnumException;
import com.woniu.utils.JwtUtil;
import com.woniu.utils.Result;
import com.woniu.utils.SMSUtil;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.*;
import lombok.Builder;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 店铺表 前端控制器
 * </p>
 *
 * @author jiang
 * @since 2024年12月09日
 */
@RestController
@RequestMapping("/store")
@Api(tags = "商户管理")
@Validated
public class StoreController {
    @Autowired
    private StoreService storeService;
    @Resource
    CommentService commentService;

    @Resource
    ProductService productService;
    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private RedisUtil redisUtil;
    @ApiOperation(value = "修改商户接单方式")
    @PutMapping("/updateHandOrder")
    @RequireRole({"商家"})
    public Result<?> updateHandOrder(@Pattern(regexp = "^(1|0)$", message = "只能是 0|1") @NotNull(message = "接单方式不能为空") Integer status, @RequestHeader("token") String token) throws Exception {
        Claims claims = JwtUtil.parseToken(token);
        String userId = claims.get("userId").toString();
        String msg = storeService.updateHandOrder(status, userId);
        return Result.getResult(String.class).setCode(200).setMsg(msg);
    }

    @GetMapping("/getStoreBoard")
    @ApiOperation(value = "获取用户的售卖信息")
    public Result<?> getStoreBoard(@RequestHeader("token") String token) throws Exception {
        Claims claims = JwtUtil.parseToken(token);
        String userId = claims.get("userId").toString();
        return Result.getResult(Object.class).setCode(200);
    }

    @GetMapping("/selectStoreByUserId")
    @ApiOperation("通过商户id查询店铺")
    @ApiImplicitParam(name = "userId", value = "商户id")
    @RequireRole({"商家","学生"})
    public Result<StoreDto> selectStoreByUserId( @Min(value = 1, message = "商户id必须为正整数") Integer userId) throws Exception {
        Store store = storeService.getOne(new QueryWrapper<Store>().eq("user_id", userId));
        if (store == null) {
            throw new StoreException("商户不存在", 10001);
        }
        Result<UserInfoFeignDto> userInfo = userFeignClient.getUserInfo(String.valueOf(userId));
        if (userInfo.getCode() != 200) {
            throw new XinanException(EnumException.NET_ERROR_EXCEPTION);
        }
        StoreDto bean = BeanUtil.toBean(store, StoreDto.class);
        bean.setUserImg(userInfo.getData().getUserImg());
        return Result.getResult(StoreDto.class).setData(bean).setCode(200).setMsg("根据商户id查询店铺信息成功");
    }
    @GetMapping("/selectStoreByToken")
    @ApiOperation("通过token查询店铺")
    @ApiImplicitParam(name = "userId", value = "商户id")
    @RequireRole({"商家","学生"})
    public Result<StoreDto> selectStoreByToken( @RequestHeader("token") String token) throws Exception {
        Claims claims = JwtUtil.parseToken(token);
        String userId = claims.get("userId").toString();
        Store store = storeService.getOne(new QueryWrapper<Store>().eq("user_id", userId));
        if (store == null) {
            throw new StoreException("商户不存在", 10001);
        }
        Result<UserInfoFeignDto> userInfo = userFeignClient.getUserInfo(String.valueOf(userId));
        if (userInfo.getCode() != 200) {
            throw new XinanException(EnumException.NET_ERROR_EXCEPTION);
        }
        StoreDto bean = BeanUtil.toBean(store, StoreDto.class);
        bean.setUserImg(userInfo.getData().getUserImg());
        return Result.getResult(StoreDto.class).setData(bean).setCode(200).setMsg("根据token查询店铺信息成功");
    }

    @GetMapping("/selectOpenTimeByStoreId")
    @ApiOperation("通过店铺id修改店铺营业时间")
    @RequireRole({"商家"})
    public Result selectOpenTimeByStoreId(@Valid  StoreOpenTimeForm storeOpenTimeForm) throws StoreException {
        storeService.selectOpenTimeByStoreId(BeanUtil.toBean(storeOpenTimeForm, StoreOpenTimeParam.class));
        return Result.getResult().setCode(200).setMsg("通过店铺id修改店铺营业时间成功");
    }

    @GetMapping("/selectAfficheByStoreId")
    @ApiOperation("通过店铺id查询店铺公告")
    @ApiImplicitParam(name = "storeId", value = "店铺id")
    @RequireRole({"商家","学生"})
    public Result selectAfficheByStoreId(@Min(value = 1, message = "店铺id必须为正整数") @Max(value = 999, message = "店铺id不能超过3位") @RequestParam Integer storeId) throws StoreException {
        String affiche = storeService.getById(storeId).getAffiche();
        return Result.getResult(String.class).setData(affiche).setCode(200).setMsg("通过店铺id查询店铺公告成功");
    }

    @GetMapping("/updateAfficheByStoreId")
    @ApiOperation("通过店铺id修改店铺公告")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "店铺id"),
            @ApiImplicitParam(name = "newAffiche", value = "新公告内容")
    })
    @RequireRole({"商家"})
    public Result updateAfficheByStoreId(@Min(value = 1, message = "店铺id必须为正整数") @Max(value = 999, message = "店铺id不能超过3位")@RequestParam  Integer storeId, @NotNull(message = "新公告内容不能为空") @Length(min = 1, max = 200, message = "公告内容长度在1-200之间")@RequestParam("newAffiche")  String newAffiche) throws StoreException {
        storeService.updateAfficheByStoreId(storeId, newAffiche);
        return Result.getResult().setCode(200).setMsg("通过店铺id修改店铺公告成功");
    }

    @PostMapping("/insertStore")
    @ApiOperation("新增店铺")
    @RequireRole({"超级管理员"})
    public Result insertStore(@Valid @RequestBody InsertStoreForm insertStoreForm) throws Exception {
        System.out.println(insertStoreForm);
        InsertStoreParam insertStoreParam = BeanUtil.toBean(insertStoreForm, InsertStoreParam.class);
        storeService.insertStore(insertStoreParam);
        return Result.getResult().setCode(200).setMsg("新增店铺店铺成功");
    }

    //    店铺基本信息修改
    @PostMapping("/modifyTheBasicInformationOfTheStore")
    @ApiOperation("店铺基本信息修改")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "license", value = "营业执照"),
            @ApiImplicitParam(name = "permit", value = "餐饮许可证")
    })
    @RequireRole({"商家"})
    public Result modifyTheBasicInformationOfTheStore(@Valid ModifyStoreForm modifyStoreForm,  MultipartFile license, MultipartFile permit, @RequestHeader("token") String token) throws Exception {
        ModifyStoreParam modifyStoreParam = BeanUtil.toBean(modifyStoreForm, ModifyStoreParam.class);
        modifyStoreParam.setLicense(license);
        modifyStoreParam.setPermit(permit);
        Claims claims = JwtUtil.parseToken(token);
        modifyStoreParam.setUserId(claims.get("userId").toString());
        modifyStoreParam.setUserName(claims.get("userName").toString());
        System.out.println(modifyStoreParam);
        storeService.modifyTheBasicInformationOfTheStore(modifyStoreParam);
        return Result.getResult().setCode(200).setMsg("店铺基本信息修改成功");
    }

    //    根据菜品名模糊查询所有拥有该菜品的店铺列表
    @GetMapping("/selectStoreByFoodName")
    @ApiOperation("根据菜品名模糊查询所有拥有该菜品的店铺列表")
    @ApiImplicitParam(name = "foodName", value = "菜品名")
    @RequireRole({"商家","学生"})
    public Result selectStoreByFoodName(@Length(min = 1, max = 15, message = "菜品名长度在1-10位之间")
                                        @NotNull(message = "菜品名不能为空") @RequestParam String foodName) throws Exception {
        List<Product> products = productService.list(new QueryWrapper<Product>().like("product_name", foodName));
        List<String> storeIds = products.stream().map(o -> o.getStoreId()).collect(Collectors.toList());
        List<Store> stores = storeService.listByIds(storeIds);
        return Result.getListResult(Store.class).setData(stores).setCode(200).setMsg("根据菜品名模糊查询所有拥有该菜品的店铺列表成功");
    }


    //    从该系统上下架该商户(修改对应店铺状态为下架),同时下架该店铺的所有菜品信息
//    @GetMapping("/disStoreByStoreId")
//    @ApiOperation("下架商铺")
//    @ApiImplicitParam(name = "storeId", value = "商户id")
//    public Result disStoreByStoreId(@NotNull(message = "用户id不能为空")
//                                    @Min(value = 1, message = "用户id必须为正整数")
//                                    @Max(value = 999, message = "用户id不能超过3位")@RequestParam  Integer storeId) throws Exception {
//        storeService.disStoreByStoreId(storeId);
//        return Result.getResult().setCode(200).setMsg("下架商铺成功");
//    }
    @PostMapping("/applyForStore")
    @ApiOperation("申请店铺")
    @RequireRole({"商家"})
    public Result<?> applyForStore(@Valid @RequestBody ApplyForStoreForm applyForStoreForm,@RequestHeader("token") String token) throws Exception {
        System.out.println(applyForStoreForm);
        Claims claims = JwtUtil.parseToken(token);
        Long userId = Long.valueOf(claims.get("userId").toString());
        Result<UserInfoFeignDto> userInfo = userFeignClient.getUserInfo(String.valueOf(userId));
        if (userInfo.getCode()!=200){
            throw new XinanException(EnumException.NET_ERROR_EXCEPTION);
        }
        Store storeServiceOne = storeService.getOne(new LambdaQueryWrapper<Store>().eq(Store::getUserId, userId));
        if (storeServiceOne!=null){
            throw new XinanException("已注册店铺，请联系后勤管理中心查询",10012);
        }
        ApplyForStoreParam applyForStoreParam = new ApplyForStoreParam();
        BeanUtil.copyProperties(applyForStoreForm,applyForStoreParam);
        applyForStoreParam.setUserId(userId);
        applyForStoreParam.setUserName(userInfo.getData().getUserName());
        System.out.println(applyForStoreParam);
        if (redisUtil.exists(RedisKey.applyForStore(String.valueOf(userId)))){
            throw new XinanException(EnumException.APPLY_FOR_STORE_EXCEPTION);
        }
        redisUtil.saveHash(RedisKey.applyList(),RedisKey.applyForStore(String.valueOf(userId)),JSONUtil.toJsonStr(applyForStoreParam));
        redisUtil.set(RedisKey.applyForStore(String.valueOf(userId)),"1",3*24*60*60);
        return Result.getResult().setCode(200).setMsg("稍后请等待短信通知或拨打8888-7777咨询");
    }
    @PostMapping("/upLoad")
    @ApiOperation("上传营业执照和卫生许可")
    @RequireRole({"商家"})
    public Result<StoreApplyFileDto> upLoad(@NotNull(message = "营业执照不可为空")@Valid MultipartFile license,@Valid @NotNull(message = "餐饮许可证不可为空") MultipartFile permit) throws Exception {
        StoreApplyFileDto storeApplyFileDto = storeService.upLoad(license, permit);
        return Result.getResult(StoreApplyFileDto.class).setCode(200).setMsg("上传营业执照和卫生许可成功").setData(storeApplyFileDto);
    }
    @GetMapping("/getApply")
    @ApiOperation("获取申请记录")
    @RequireRole({"超级管理员"})
    public Result<StoreApplyPageDto> getApply(
            @Min(value = 1,message = "页码必须为正整数")
            @Max(value = 100,message = "每页行数不能超过100")
            @ApiParam("页码")
            Integer pageNum ,
            @ApiParam("每页行数")
            @Min(value = 1,message = "页码必须为正整数")
            @Max(value = 100,message = "每页行数不能超过100")
            Integer pageSize) throws Exception {
        pageNum = pageNum==null?1:pageNum;
        pageSize = pageSize==null?5:pageSize;
        List<StoreAppliesDto> applyForStore = new ArrayList<>();
        Map<Object, Object> objectObjectMap = redisUtil.hgetAll(RedisKey.applyList());
        List<StoreAppliesDto> finalApplyForStore = applyForStore;
        objectObjectMap.entrySet().stream().forEach(o->{
            if (o.getValue()!=null){
                StoreAppliesDto bean = JSONUtil.toBean(o.getValue().toString(), StoreAppliesDto.class);
                bean.setTLL(redisUtil.getExpire(RedisKey.applyForStore(String.valueOf(bean.getUserId()))));
                finalApplyForStore.add(bean);
            }
        });
        int total = finalApplyForStore.size();
        int pageSum = total%pageSize==0?total/pageSize:total/pageSize+1;
        applyForStore = finalApplyForStore.stream().skip((pageNum-1)*pageSize).limit(pageSize).collect(Collectors.toList());
        StoreApplyPageDto storeApplyPageDto = new StoreApplyPageDto();
        storeApplyPageDto.setPages(pageSum);
        storeApplyPageDto.setPageNum(pageNum);
        storeApplyPageDto.setPageSize(pageSize);
        storeApplyPageDto.setTotal(total);
        storeApplyPageDto.setList(applyForStore);
        return Result.getResult(StoreApplyPageDto.class).setCode(200).setMsg("申请记录查询成").setData(storeApplyPageDto);
    }
    @DeleteMapping("/noApply")
    @ApiOperation("申请未通过记录")
    @RequireRole({"超级管理员"})
    public Result noApply(@ApiParam("用户编号") Long userId) throws Exception {
        redisUtil.del(RedisKey.applyForStore(String.valueOf(userId)));
        redisUtil.removeHash(RedisKey.applyList(),RedisKey.applyForStore(String.valueOf(userId)));
        Result<UserInfoFeignDto> userInfo = userFeignClient.getUserInfo(String.valueOf(userId));
        if (userInfo.getCode()!=200){
            throw new XinanException(EnumException.NET_ERROR_EXCEPTION);
        }
        SMSUtil.sendCode(userInfo.getData().getUserPhone(),"1");
        return Result.getResult().setMsg("申请未通过记录删除成功").setCode(200);
    }
    @GetMapping("/getStoreApplyOvertime")
    @ApiOperation("获取申请记录超时时间")
    @RequireRole({"超级管理员"})
    public Result<StoreApplyPageDto> getStoreApplyOvertime(
            @Min(value = 1,message = "页码必须为正整数")
            @Max(value = 100,message = "每页行数不能超过100")
            @Pattern(regexp = "^[1-9]\\d*$",message = "页码必须为正整数")
            @ApiParam("页码")
            Integer pageNum ,
            @ApiParam("每页行数")
            @Min(value = 1,message = "页码必须为正整数")
            @Max(value = 100,message = "每页行数不能超过100")
            @Pattern(regexp = "^[1-9]\\d*$",message = "页码必须为正整数")
            Integer pageSize
    ) throws Exception {
        pageNum = pageNum==null?1:pageNum;
        pageSize = pageSize==null?5:pageSize;
        List<StoreAppliesDto> finalApplyForStore = storeService.removeStoreAppliesTime();
        int total = finalApplyForStore.size();
        int pageSum = total%pageSize==0?total/pageSize:total/pageSize+1;
        finalApplyForStore = finalApplyForStore.stream().skip((pageNum-1)*pageSize).limit(pageSize).collect(Collectors.toList());
        StoreApplyPageDto storeApplyPageDto = new StoreApplyPageDto();
        storeApplyPageDto.setPages(pageSum);
        storeApplyPageDto.setPageNum(pageNum);
        storeApplyPageDto.setPageSize(pageSize);
        storeApplyPageDto.setTotal(total);
        storeApplyPageDto.setList(finalApplyForStore);
        return Result.getResult(StoreApplyPageDto.class).setCode(200).setMsg("查询超时申请成功").setData(storeApplyPageDto);
    }

}

